package com.lzrj.server;

import com.lzrj.utlis.ZipUtils;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Server;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import sun.misc.Signal;
import sun.misc.SignalHandler;
import java.io.File;
import java.io.IOException;
import java.util.List;


public class WebServer {

    public static void startCmd(CmdArgOption arg) {
        File file = new File(".");

        try {
            Runtime.getRuntime().exec("");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动tomcat
     */
    public static void start(CmdArgOption arg) {

        Tomcat tomcat = new Tomcat();
        tomcat.setPort(arg.getServerPort());
        tomcat.setHostname(arg.getHostname());
        tomcat.setBaseDir(arg.getBasedir()); // tomcat 信息保存在项目下
//        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
//        connector.setThrowOnFailure(true);
//        tomcat.getService().addConnector(connector);
//        tomcat.setConnector(connector);
//        tomcat.getHost().setAutoDeploy(true);


        List<Webapp> webapps = arg.getParseWebapp();
        // 遍历判断是否是war包，是war则解压
        for (Webapp app : webapps) {
            String path = app.getPath();
            if (path.endsWith(".war")){
                // 参数中项目路径是一个war包，则先在war包的父级目录下解压war
                File warFile = new File(path);
                String warName = warFile.getName();
                path = warFile.getParent()+File.separator+warName.substring(0,warName.lastIndexOf(".war"));
                File appFile = new File(path);
                if (!appFile.exists() || warFile.lastModified() > appFile.lastModified()){
                    ZipUtils.unZip(warFile,path);
                    appFile.setLastModified(System.currentTimeMillis());
                }
                app.setPath(path);
            }
        }


        try {
            /*
             * tomcat加入web工程
             * host:缺省默认为localhost
             * contextPath:在浏览器中访问项目的根路径
             * 例：localhost:port/{contextPath}/xx
             * docBase：项目中webapp所在路径
             */
//          tomcat.addWebapp(host, contextPath, docBase)
//          myCtx.setJavaVMs(arg.getJvmParams().toArray(new String[0]));
//          myCtx.setConfigFile();
//          myCtx.setDefaultContextXml();
//          myCtx.setJavaVMs();
            for (Webapp app : webapps) {
                StandardContext myCtx = (StandardContext) tomcat.addWebapp(app.getContext(), new File(app.getPath()).getAbsolutePath());
                myCtx.setJavaVMs(arg.getJvmParams().toArray(new String[0]));
               // tomcat.addWebapp();
            }
            tomcat.start();

            System.out.println("Web Application start success......");
        } catch (Exception e) {
            tomcat = null;
            System.out.println("Web Application start fail......");
            e.printStackTrace();
        }finally {
            if (tomcat != null){
                Server server = tomcat.getServer();
                String catalinaBase = server.getCatalinaBase().getAbsolutePath();
                System.setProperty("user.dir",catalinaBase);
                // 监听操作系统中断信号
                signalListen(tomcat);
                // 将进程信息写入到文件中
                ProcessInfo.writeProcessInfo(webapps, arg.getServerPort() , catalinaBase);
                // 阻塞线程
                startDaemonAwaitThread(tomcat);
            }
        }
    }


    /**
     * 监听操作系统中断信号
     * @param tomcat tomcat实例
     */
    public static void signalListen(Tomcat tomcat){

        SignalHandler signalHandler = new SignalHandler() {
            @Override
            public void handle(Signal signal) {
                if (tomcat != null){
                    int webPort = tomcat.getConnector().getPort();
                    try {
                        ProcessInfo.removeProcessInfoFile(webPort);
                        tomcat.stop();
                        tomcat.destroy();
                    } catch (LifecycleException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("SignalHandler: " + signal);
            }
        };

        // 只有kill -9能够结束jvm进程，别的信号量只是发送给java进程处理，至于如何响应是程序代码决定的
        signalHandle("HUP",signalHandler);// kill -1 PID
        signalHandle("INT",signalHandler);// kill -2 PID
        // already used by VM or OS: SIGQUIT
        signalHandle("QUIT",signalHandler);// kill -3 PID
        signalHandle("ABRT",signalHandler);// kill -6 PID
        // already used by VM or OS: SIGKILL
        //Signal.handle(new Signal("KILL"), signalHandler); // kill -9 PID
        signalHandle("ALRM",signalHandler);// kill -14 PID
        signalHandle("TERM",signalHandler); // kill -15 PID
    }


    private static void startDaemonAwaitThread(Tomcat tomcat) {
        Thread awaitThread = new Thread("tomcat-" + tomcat.getConnector().getPort()) {
            public void run() {
                tomcat.getServer().await();
            }
        };
        awaitThread.setContextClassLoader(WebServer.class.getClassLoader());
        awaitThread.setDaemon(false);
        awaitThread.start();
    }

    private static void signalHandle(String sign,SignalHandler signalHandler){
        try {
            Signal.handle(new Signal(sign), signalHandler); // kill -1 PID
        }catch (Exception e){
            e.printStackTrace();
        }
    }


}
